
package CLIENT;

import GUI.*;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.UnknownHostException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.border.BevelBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

/**
 * This Class Handles all the Main Chat Panel functionalities and the GUI For Main Chat
 * @author Yaniv Kalif
 */

public class ClientMainChatPanel extends JPanel implements MouseListener,ActionListener,KeyListener,ListSelectionListener
{
    //***********Initialize GUI Arguments****************//
    List<PrivateChatFrame> _PrivateChatFrameList = new LinkedList<PrivateChatFrame>();
    JTextArea _textArea; // The Text Area for the main chat (everyones messages)
    JScrollPane text_Scroll;//the scroller for the main chat area
    JList _userList;//displays the users list
    DefaultListModel listModel;//the actually list of the users
    JScrollPane user_scroll;//the scroller for user list
    JTextArea _messageField;//the message field
    JScrollPane mess_Scroll;//the scroller for the message field
    EmoticonsPanel _Emoticons;//the EmoticonsPanel panel
    JButton _send,_history,_sendFile;//the "send" button
    Font _font;//the main Font
    Color _TA_Color;//The Text Areas color
    Color _BG_Color;//The Background color
    Image _image3DP;
    Image _image3DP_red;
    Image _image3DP_run;
    Image _imagetitle;
    //**********************************************//
    //***********Initialize The File Arguments****************//
    String folderPath = System.getProperty("user.dir");
    File  logFile;
    //***********Initialize NETWORK Arguments****************//
    ClientMessageListener _messagelistener;
    ClientConnection _clientconnection;
    Client _client;
    /**
     * constructor for MainChatPanel
     * This contructor:
     * * setting the images
     * * setting the colors
     * * initializing: users list , TextArea , EmoticonsPanel Panel, Message Field and the "send" button
     */
    public ClientMainChatPanel(Client c, ClientConnection client) throws IOException
    {
        //Setting the Layout Manager
            setLayout(null);

        //Set the Image
            _image3DP = Toolkit.getDefaultToolkit().getImage("Pics/3D Postman.gif");
            _image3DP_red = Toolkit.getDefaultToolkit().getImage("Pics/3D Postman with large red.gif");
            _image3DP_run = Toolkit.getDefaultToolkit().getImage("Pics/3D Postman running copy.gif");
            _imagetitle = Toolkit.getDefaultToolkit().getImage("Pics/talk2me.gif");
        //Create/Set Colors
            _TA_Color=new Color(152, 251, 152);//create TextArea color
            _BG_Color=new Color(60,179,113);//create BG color
            this.setBackground(_BG_Color);

         //Initialize Font
            _font=new Font("Arial",Font.BOLD,13);
         //initialize model list
            listModel = new DefaultListModel();
         //initialize List
                _userList=new JList(listModel);
                _userList.setVisibleRowCount(20);
                _userList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);//make sure you can choose only one user at one time
                _userList.setLayoutOrientation(0);// VERTICAL
                _userList.setBackground(_TA_Color);
                _userList.setFont(_font);
                _userList.setToolTipText("Choose one user to enter a Private chat Window");
                _userList.setDragEnabled(true);
                _userList.addListSelectionListener(this);
                user_scroll=new JScrollPane(_userList, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
                user_scroll.setBorder(new TitledBorder(new BevelBorder(BevelBorder.LOWERED),"Users List"));//set the border for the user scroller+title
                this.add(user_scroll);
                user_scroll.setBounds(200, 150, 150, 400);
                
        //Initialize TextArea
                _textArea = new JTextArea();
                _textArea.setFont(_font);
                _textArea.setBackground(_TA_Color);
                _textArea.setEditable(false);
                _textArea.setToolTipText("Main Chat - Here you'll see all the messages in the community");
                text_Scroll=new JScrollPane(_textArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
                text_Scroll.setBounds(350, 150, 600, 400);
                text_Scroll.setBorder(new TitledBorder(new BevelBorder(BevelBorder.LOWERED),"Main Chat"));//set the border for the text scroller+title
                this.add(text_Scroll);

        //initialize EmoticonsPanel(Panel)
            _Emoticons=new EmoticonsPanel();
//              _Emoticons.setBounds(350, 550, 1000, 5);
            _Emoticons.setBounds(350, 550, 350, 30);
                       for(int i=0;i<_Emoticons._size;i++)
            _Emoticons._Buttons[i].addMouseListener(this);
            this.add(_Emoticons);

        //initialize message field
            _messageField=new JTextArea("Enter your message here . . .");
            _messageField.setFont(_font);
            _messageField.setToolTipText("Enter Your Message Here . . .");
            _messageField.setColumns(50);
            mess_Scroll=new JScrollPane(_messageField, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
            mess_Scroll.setBounds(350, 585, 500, 50);
            _messageField.setBorder(new BevelBorder(BevelBorder.LOWERED));
            _messageField.addKeyListener(this);
            this.add(mess_Scroll);

        //initialize "send" button
            _send=new JButton("SEND");
            _send.setBounds(850, 585,100,50);
            _send.addMouseListener(this);
            _send.addActionListener(this);
            _send.setBorder(new BevelBorder(BevelBorder.RAISED));
            this.add(_send);
              _sendFile=new JButton("SEND File");
            _sendFile.setBounds(850, 585,100,50);
            _sendFile.addMouseListener(this);
            _sendFile.addActionListener(this);
            _sendFile.setBorder(new BevelBorder(BevelBorder.RAISED));
             this.add(_sendFile);
            //initialize "history" button
             _history=new JButton("HISTORY");
//            _history.setBounds(960, 585,100,50);
             _history.setBounds(950, 150,100,50);
            _history.addMouseListener(this);
            _history.addActionListener(this);
            _history.setBorder(new BevelBorder(BevelBorder.RAISED));
            this.add(_history);

       //initialize NETWORK
        _client =c;
        _clientconnection=client;
        _client._socket = _clientconnection.GetConnectedSocket();
         _messagelistener = new ClientMessageListener(_clientconnection, this);
        Thread T = new Thread(_messagelistener);
        T.start();

        //initialize log file
        logFile = new File(folderPath + "\\History "+_client.GetName()+".txt");//the path to the history file
        
    }
    @Override
    /**
     * Paint component override
     * This function draws all The Regular component + draws The images + The BG by Theme
     */
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        //draw the images
            g.drawImage(_image3DP, -70, -20, null);
            g.drawImage(_image3DP_run, 130 , 550, null);
            g.drawImage(_image3DP_red, 950, 300, null);
            g.drawImage(_imagetitle, 300, -40, null);

        //paint the color of the panel and he's components by the colors of the theme
            this.setBackground(_BG_Color);
            _textArea.setBackground(_TA_Color);
            _userList.setBackground(_TA_Color);
            _messageField.setBackground(_TA_Color);
            text_Scroll.setBackground(_TA_Color);
            user_scroll.setBackground(_TA_Color);
            
    }
    /**
 * this function changes the "theme" of the panel by changing the BackGroung color and the TextArea color
 * @param BG the new Background color
 * @param TA the new TextArea color
 */
    public void ChangeTheme(Color BG,Color TA)
    {
        if(BG==Color.black)
            _imagetitle = Toolkit.getDefaultToolkit().getImage("Pics/talk2me opp.gif");
        else
            _imagetitle = Toolkit.getDefaultToolkit().getImage("Pics/talk2me.gif");

        _TA_Color=TA;
        _BG_Color=BG;
        repaint();
    }
    /**
     * This inherited function handles events on emoticons buttons
     * @param e MouseEvent that accured
     */
    public void mouseClicked(MouseEvent e)
    {
        String s=_messageField.getText();
        _messageField.setText(null);

        //EmoticonsPanel events
                if(e.getSource()==_Emoticons._Buttons[0])//happy
                {
                    _messageField.insert(s+":-)",0);
                }
                if(e.getSource()==_Emoticons._Buttons[1])//sad
                {
                    _messageField.insert(s+":-(",0);
                }
                if(e.getSource()==_Emoticons._Buttons[2])//wink
                {
                    _messageField.insert(s+";-)",0);
                }
                if(e.getSource()==_Emoticons._Buttons[3])//angry
                {
                    _messageField.insert(s+">:(",0);
                }

        if(e.getSource()==_Emoticons._Buttons[3])//angry
                {
                    _messageField.insert(s+">:(",0);
                }
        if(e.getSource()==_Emoticons._Buttons[4])//XD
                {
                    _messageField.insert(s+">:(",0);
                }
        if(e.getSource()==_Emoticons._Buttons[5])//confused
                {
                    _messageField.insert(s+">:(",0);
                }
        if(e.getSource()==_Emoticons._Buttons[6])//frown
                {
                    _messageField.insert(s+">:(",0);
                }
        if(e.getSource()==_Emoticons._Buttons[7])//lol
                {
                    _messageField.insert(s+">:(",0);
                }
        if(e.getSource()==_Emoticons._Buttons[8])//biggrin
                {
                    _messageField.insert(s+">:(",0);
                }
        if(e.getSource()==_Emoticons._Buttons[9])//neutural
                {
                    _messageField.insert(s+">:(",0);
                }
        if(e.getSource()==_Emoticons._Buttons[10])//oh
                {
                    _messageField.insert(s+">:(",0);
                }
        if(e.getSource()==_Emoticons._Buttons[11])//teeth
                {
                    _messageField.insert(s+">:(",0);
                }
        if(e.getSource()==_Emoticons._Buttons[12])//winktongue
                {
                    _messageField.insert(s+">:(",0);
                }

        
    }
    /**
     * This inherited function handles events on "send" Button and "History" Button
     * @param e ActionEvent that accured
     */
    public void actionPerformed(ActionEvent e)
    {
        //"send" pressed
        if(e.getSource()==_send)
        {
            try 
            {
                String s = _messageField.getText();
                _messageField.setText(null);
                Calendar cal = Calendar.getInstance();
                String time = "(" + cal.get(Calendar.HOUR_OF_DAY) + ":" + cal.get(Calendar.MINUTE) + ":" + cal.get(Calendar.SECOND) + ")";
                String all=_textArea.getText();
                _textArea.setText(all+_client.GetName() + time + " :\n\t" + s + "\n");
                 _clientconnection.SendMessage(_client, s); // sending the message to the server

                //save sent maessage to history file
                DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
                String fullTime = dateFormat.format(new Date());
                fullTime = dateFormat.format(new Date());
                String msgToFile = fullTime +" " + _client.GetName()+" SAID : " + s;
                SaveHistory(logFile, msgToFile); //save the massage into file
            }
            catch (IOException ex)
            {
                Logger.getLogger(ClientMainChatPanel.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

         //"history" pressed
        if(e.getSource()==_history)
        {
            LoadFile(logFile);
        }
        
    }
    /**
     * This inherited function handles eyboard events
     * @param e Keyboard Event that accured
     */
     public void keyPressed(KeyEvent e)//conects the "enter" key to the "send" button
    {
        if(KeyStroke.getKeyStrokeForEvent(e)==KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0))
        {
            this.actionPerformed(new ActionEvent(_send, 0, null));
        }
    }
    public void keyTyped(KeyEvent e){}
    public void keyReleased(KeyEvent e) {}

    /**
     * this function accurs every time an action on the _userList happens
     * the function will open a new private window
     * @param e ListSelectionEvent that accured
     */
    public void valueChanged(ListSelectionEvent e)
    {
       
                //********** private chat event ************//
                    Object s=_userList.getSelectedValue();
                    if(s!=null)
                    {
                        PrivateChatFrame p;
                        p=new PrivateChatFrame((String) s, _clientconnection.out, _client);
                        p.setVisible(true);
                        _PrivateChatFrameList.add(p);
                    }

    }
    /**
     * This function Recieves a new message and handles it's delivery.
     * if it's a regular message it will appear in the TextArea of the public chat
     * if it's a personal message it will move to the correct privateChatPanel That needs to recieve it. (if no private panel that fit it will open a new PrivateChatFrame
     * @param msg - The message that recieved
     * @throws IOException
     * @throws UnknownHostException
     * @throws InterruptedException
     */
    void RecieveMessage(Message msg) throws IOException, UnknownHostException, InterruptedException
    {
        if (msg.GetClientdst()==null)
        {
            Calendar cal=Calendar.getInstance();
            String time="("+cal.get(Calendar.HOUR_OF_DAY)+":"+cal.get(Calendar.MINUTE)+":"+cal.get(Calendar.SECOND)+")";
            String all=_textArea.getText();
            _textArea.setText(all+msg.GetClientsrc()+time+" :\n\t"+msg.GetString()+"\n");
            Toolkit.getDefaultToolkit().beep();

            //save recieved messages to history file
            DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
            String fullTime = dateFormat.format(new Date());
            fullTime = dateFormat.format(new Date());
            String msgToFile = fullTime +" " + msg.GetClientsrc() +" SAID : " + msg.GetString();
            SaveHistory(logFile, msgToFile); //save the massage into file
        }
        else//if it's a personal message
        {
            boolean flag=false;
            for (int i=0; i<_PrivateChatFrameList.size(); i++)
            {
                if (_PrivateChatFrameList.get(i).GetChatWith().equals(msg.GetClientsrc()))
                {
                    _PrivateChatFrameList.get(i).GetPrivateChatP().RecieveMessage(msg);
                    flag=true;
                }
            }
            if(flag==false)//no private chat panel for this user
            {
                        PrivateChatFrame p;
                        p=new PrivateChatFrame(msg.GetClientsrc(), _clientconnection.out, _client);
                        p.setVisible(true);
                        _PrivateChatFrameList.add(p);
                        p.GetPrivateChatP().RecieveMessage(msg);
            }

        }
    }
    /**
     * this method loads the history file to the TextArea
     * @param fileToLoad the history file to load to the TextArea
     */
    private void LoadFile(File fileToLoad)
    {
        // Load file
        String fileNameToLoad = fileToLoad.getPath();
        BufferedReader br = null;
        String bufLine = null;

        try {

            br= new BufferedReader(new FileReader(fileToLoad));
            String allText=_textArea.getText();
            _textArea.setText(allText + "************* HISTORY *************" + "\n");
            while (br.ready())
            {
                //read one line at the time from the save file
                bufLine= br.readLine();
                allText=_textArea.getText();
                _textArea.setText(allText + bufLine + "\n");
                bufLine=null;
            }
            allText=_textArea.getText();
            _textArea.setText(allText + "************* END HISTORY *************" + "\n");
        }
             catch (FileNotFoundException x) {
                x.printStackTrace();}
        catch (IOException x) {
                x.printStackTrace();
        }

    }

    /**
     * This method saves a msg to a txt file
     * @param selectedFile the file to save the history to
     * @param msg the message to save to the selected file
     */
    private void SaveHistory(File selectedFile , String msg)
    {
        String _in;
        try{
                BufferedWriter fileWriter =  new BufferedWriter(new FileWriter(selectedFile, true));
                _in = msg;
                fileWriter.write(_in); //Write out the specfied string to the file
                fileWriter.newLine(); //download one line between each point
                fileWriter.flush(); //flushes and closes the stream
                fileWriter.close();
        }

        catch(IOException e)
        {
            System.out.println("There was a problem:" + e);
        }
    }
    Client GetClient(){return _client;}
    /**
     * This function adds a new user to the users list
     * @param Nickname - the new user NickName
     */
    void AddUserToList(String Nickname) {
        listModel.addElement(Nickname);
        repaint();
    }

    void ClearUsersList() {
        listModel.removeAllElements();
        repaint();
    }
    /**
     * This function Closes all the connection and Usibility of this panel
     * @throws IOException
     */
    public void CLOSEALL() throws IOException
    {
        _clientconnection.Disconnect();
        _messagelistener.in.close();
    }
    public void mousePressed(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) { }
    public void mouseEntered(MouseEvent e) {  }
    public void mouseExited(MouseEvent e) {    }
}
